﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DrDimsLib.CommonTool.Extensions
{
    using System.ComponentModel;
    using System.Security.Cryptography;


    #region 字符串加密函数和转码函数|切割比特流函数
    public static class DealWithStringCrypto
    {
        /// <summary>
        /// 对字符串的常见操作 工具类 集成方式为 CLR系统扩展
        /// using 导入命名空间可直接使用
        /// <code>
        ///     using DrDimsLib.CommonTool;
        ///     
        ///     var md5String = "哈哈".toMD5String();
        ///     var SHA1String = "哈哈".ToSHA1String()
        ///     var SHA256 = "哈哈".ToSHA1String(SHA256);
        ///     
        /// </code>
        /// </summary>
        public enum bTypeHashWay
        {
            Bit16, Bit32, SHA1, SHA256
        }
        [Description("非对称加密算法 的常规参数枚举 1.MD5 2.SHA1 3.SHAxxx")]
        static private readonly Encoding codingType = Encoding.UTF8;

        [Description("字节数组16进制表达")]
        private static char[] HEX = new char[] {
            '0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f',
        };
        /// <summary>
        /// 对比特数据进行16bit的高位对齐 `F 2 3 4 3 D` ---> `F2 34 3D` 2位 
        /// 合成一个byte字面值char 不足的高位b用0对齐 `FD3` ---> `0F D3`
        /// </summary>
        /// <param name="bContent">需要转换成 16 进制的字节数组</param>
        /// <returns>乱码替换之后的自然语言MD5表达</returns>
        static public string bytes2Hex(byte[] bContent)
        {
            char[] chs = new char[bContent.Length * 2];
            for (int i = 0, offset = 0; i < bContent.Length; i++)
            {
                chs[offset++] = HEX[bContent[i] >> 4 & 0xf];
                chs[offset++] = HEX[bContent[i] & 0xf];
            }
            return new String(chs);
        }
        // 扩展类必须指定统一的编码方式 为了兼容移动端和多国语言 这里使用UTF8
        // 如果节省带宽 请使用 Encoding.Default(GBK国标码)
        public static string ToMD5String(
            this string originString,
            bTypeHashWay type = bTypeHashWay.Bit32
            )
        {
            HashAlgorithm codeBytes = new MD5CryptoServiceProvider();
            byte[] 加密之后的比特数组 = codeBytes.ComputeHash(codingType.GetBytes(originString));
            string rs = bytes2Hex(加密之后的比特数组);
            switch (type)
            {
                case bTypeHashWay.Bit16:
                    var startIndex = rs.Length / 4;
                    return rs.Substring(startIndex, 16);
                case bTypeHashWay.Bit32:
                default:
                    return rs;
            }
            throw new Exception("HashBitTypeError - 加密枚举参数传错了~");
        }
        /// <summary>
        /// SHA1 - 数字摘要算法 SHA1
        /// </summary>
        /// <param name="originString">需要加密的原始字串</param>
        /// <returns>加密之后的自然语言String表达SHA1 32位 </returns>
        public static string ToSHA1String(this string originString,
            bTypeHashWay bType = bTypeHashWay.SHA1)
        {
            HashAlgorithm codeBytes = null;
            switch (bType)
            {
                case bTypeHashWay.SHA1:
                    codeBytes = new SHA1CryptoServiceProvider();
                    break;
                case bTypeHashWay.SHA256:
                    codeBytes = new SHA256CryptoServiceProvider();
                    break;
                default:
                    return originString.ToMD5String();
            }
            var bArray = codeBytes.ComputeHash(codingType.GetBytes(originString));
            return bytes2Hex(bArray);
        }

        /// <summary>
        /// 字符混淆算法 Base64 StringEncoding
        /// </summary>
        /// <param name="originString"></param>
        /// <returns></returns>
        public static string ToBase64String(this string originString)
        {
            return Convert.ToBase64String(codingType.GetBytes(originString));
        }
    }
    #endregion
}
